import { BadRequestException, HttpCode, HttpException, HttpStatus, Inject, Injectable, UnauthorizedException } from "@nestjs/common";
import { CreateUserDto } from "./dto/create-user.dto";
import { PrismaService } from "@/common/prisma/prisma.service";
import { handleError } from "@/utils/handle.error";
import { LoggerService } from "@/common/logger/logger.service";
import { hash, compare } from 'bcryptjs';
import { UpdateUserDto } from "./dto/update-user.dto";
import { RedisService } from "@/common/redis/redis.service";
import { RedisKeyEnum } from "@/common/enums/redis-key.enum";
@Injectable()
export class UserService {
  @Inject(LoggerService)
  private readonly logger: LoggerService;

  @Inject(PrismaService)
  private readonly prismaService: PrismaService;

  @Inject(RedisService)
  private readonly redisService: RedisService;


  async register(createUserDto: CreateUserDto) {
    this.logger.log(`${this.register.name} was called`);
    try {
      const { name, password, phone, avatar, email } = createUserDto;
      const saltPwd = await hash(password, 10);
      const data = await this.prismaService.user.findFirst({
        where: {
          OR: [
            {
              name,
            },
            {
              phone,
            },
          ],
        }
      })
      if (data) {
        let msg = '已存在'
        if (phone === data.phone) {
          msg = `手机号${phone}${msg}`
        }
        if (name === data.name) {
          msg = `用户名${name}${msg}`
        }
        throw new BadRequestException(msg)
      }
      const { id } = await this.prismaService.user.create({
        data: { name, phone, avatar, email, password: saltPwd },
        select: {
          id: true,
        },
      });
      return id;
    } catch (error) {
      handleError(this.logger, error, {
        common: "创建用户失败",
      });
    }
  }


  async findUserById(id: number) {
    this.logger.log(`${this.findUserById.name} was called`);
    try {
      const user = await this.prismaService.user.findUnique({
        where: { id, isDelete: false },
        select: {
          id: true,
          name: true,
          avatar: true,
          phone: true,
          email: true,
        },
      })
      if (!user) throw new BadRequestException("该用户不存在");
      return user;
    } catch (error) {
      handleError(this.logger, error, {
        common: "查找用户失败",
      });
    }
  }

  async updateUser(updateUserDto: UpdateUserDto) {
    this.logger.log(`${this.updateUser.name} was called`);
    try {
      const { id, name, avatar, phone, email } = updateUserDto
      const findUser = await this.findUserById(id)
      if (!findUser) throw new HttpException('用户不存在', HttpStatus.OK);
      const user = await this.prismaService.user.update({
        where: {
          id,
          isDelete: false
        },
        data: {
          name,
          avatar,
          phone,
          email
        }
      })
      return user;
    } catch (error) {
      handleError(this.logger, error, {
        common: "更新用户失败",
      });
    }
  }


  async validateUserByPwd(name: string, password: string) {
    this.logger.log(`${this.validateUserByPwd.name} was called`);
    try {
      // 查找用户
      const user = await this.prismaService.user.findUnique({
        select: {
          id: true,
          name: true,
          password: true,
          email: true,
          phone: true,
          avatar: true,
        },
        where: {
          name,
          isDelete: false,
        }
      })
      // 判断用户是否存在
      if (!user) throw new UnauthorizedException("用户不存在");
      // 判断密码是否正确
      const isPwdValid = await compare(password, user.password);
      //密码不正确
      if (!isPwdValid) throw new UnauthorizedException("账号或密码错误");
      const { password: _password, ...result } = user
      return result;
    } catch (error) {
      handleError(this.logger, error, {
        common: "验证用户失败",
      });
    }
  }


  async validateUserByEmail(email: string, code: string) {
    this.logger.log(`${this.validateUserByEmail.name} was called`);
    try {
      const redisCode = await this.redisService.get(RedisKeyEnum.LoginKey + email)
      if (!redisCode) { throw new HttpException('验证码不存在，请输入正确验证码', HttpStatus.OK) }
      if (redisCode && redisCode !== code) { throw new HttpException('验证码错误，请重新输入', HttpStatus.OK) }
      // 查找用户
      const user = await this.prismaService.user.findFirst({
        select: {
          id: true,
          name: true,
          password: true,
          email: true,
          phone: true,
          avatar: true,
        },
        where: {
          email,
          isDelete: false,
        }
      })
      // 判断用户是否存在
      if (!user) throw new UnauthorizedException("用户不存在");
      return user;
    } catch (error) {
      handleError(this.logger, error, {
        common: "验证用户失败",
      });
    }
  }

  /**
   * 记录用户ip
   * @param id 用户id
   * @param ip 用户ip
   * @returns
   */
  async recordUserIp(id: number, ip: string) {
    this.logger.log(`${this.recordUserIp.name} was called`);
    try {
      await this.prismaService.user.update({
        where: { id },
        data: { ip },
      });
    } catch (error) {
      handleError(this.logger, error, { common: "记录用户ip失败" });
    }
  }



}
